\chapter{Вікірозмітка}

\section{Види}
В даній роботі будемо розглядати розмітку рушія MediaWiki, проте не варто забувати, що існує ще багато подібних розміток, наприклад:
\begin{itemize}
\item Google Code Wiki
\item DokuWiki (також підтримує Creole)\cite{creolesoft}
\item MoinMoin (також підтримує Creole)\cite{creolesoft}
\item txt2tags (підтримує трансляцію у всі попередні а також MediaWiki)
\item Creole — спроба описати спільну мову розмітки вікі, що буде використовуватися у різних вікі\cite{creole}.
\end{itemize}

що використовуються на найрізноманітніших сайтах. Навіть такі популярні сайти як \href{http://vkontakte.ru/}{vkontakte.ru}\cite{vkru}, \href{http://wordress.com/}{wordpress.com}, \href{http://stackoverflow.com/}{stackoverflow.com} використовують свої діалекти вікірозмітки.

\begin{figure}
\includegraphics[width=0.8\textwidth]{wikimarkupterm.png} 
\centering \caption{Зразок підсвіченої вікірозмітки}
\end{figure}

\section{Абзаци та розділи}
В вікірозмітці, як і в \LaTeX, абзаци розділяються за допомогою порожнього рядка\cite{howtoedit}.

Заголовки розділів виділяються за допомогою знаків дорівнює:
\begin{verbatim}
== Розділ ==
=== Підрозділ ===
==== 4 рівень ====
===== 5 рівень =====
====== 6 рівень ======
\end{verbatim}

\section{Посилання}
Найважливішим елементом вікірозмітки після абзаців звісно є посилання. Розмітка для посилання навіть зображена на логотипі MediaWiki. Посилання бувають двох видів - внутрішнє (в межах однієї вікі), на зовнішній сайт, та на дружній ресурс (майже можна вважати за внутрішнє).

Внутрішнє посилання задається подвійними квадратними дужками:
\begin{verbatim}
[[Посилання]]
\end{verbatim}
Таким чином слово "посилання" стає гіперпосиланням на статтю "посилання". Якщо нам треба змінити текст посилання, чи послатись на іншу статтю, пишемо:
\begin{verbatim}
[[Назва статті|Посилання]]
\end{verbatim}

Також можна послатись на конкретний розділ статті (незалежно від рівня), дописавши його назву відділену символом дієз:
\begin{verbatim}
[[Назва статті#Розділ|Текст посилання]]
\end{verbatim}

Якщо ми хочемо послатись на дружній вікіресурс, дописуємо до початку посилання префікс цього вікіресурсу. Наприклад:
\begin{verbatim}
[[b:Назва підручника|Посилання на вікіпідручник]]
\end{verbatim}

Для посилання на зовнішній сайт, використовують одинарні квадратні дужки, і в них зліва пишуть адресу посилання, а зправа його текст:
\begin{verbatim}
[http://uk.wikipedia.org Українська вікіпедія]
\end{verbatim}

\section{Списки}
\begin{verbatim}
* Створювати списки дуже просто:
** починайте рядок з "зірочки"
*** кількість зірочок означає рівень в ієрархічному списку

# Нумеровані списки
## зручні
## для організації даних

* Можна створювати змішані списки
*# та вкладати їх
*#* один в один

; Список означень : список, в якому замість цифр, чи 
 маркерів елементів використовують певні терміни. 
 В вікірозмітці створюється за допомогою крапки з комою та двокрапки.
\end{verbatim}

\section{Форматування тексту}
Якщо почати рядок тексту з пропуска, чи помістити рядки в тег \verb!<pre></pre>!, то отримаємо попередньо відформатований текст.

Можна використовувати підсвітку синтаксису мов програмування за допомогою тегу \verb!<source lang="html"></source>!. Для підсвічування використовується PHP бібліотека Geshi.

Двокрапка що стоїть на початку рядка додає додатковий відступ зліва. Цих двокрапок може бути довільна кількість.

Одинарні лапки дозволяють форматувати текст жирним та курсивом.

\begin{verbatim}
''Курсив'', '''жирний''', '''''жирний курсив'''''.
\end{verbatim}

\section{HTML}
Вікірозмітка MediaWiki включає в себе деяку підмножину тегів HTML. Наприклад \verb!<u></u>! для підкресленого тексту, \verb!<strike></strike>! - перекресленого, \verb!<tt></tt>! - оформленого машинописним шрифтом, та подібні. 

Коментарі в вікірозмітці записуються так само як і коментарі в HTML:
\begin{verbatim}
<!-- коментар -->
\end{verbatim}

Також доступні html теги для оформлення таблиць, \verb!<div></div>!, та CSS в атрибутах \verb!style!, тому в оформленні статтей можна використовувати всі можливості табличної чи блочної верстки.

\section{Таблиці}
Вікірозмітка має зручніший синтаксис для створення таблиць ніж HTML. Виглядають вони приблизно так:

\begin{verbatim}
{| <!-- тут вписують атрибути таблиці. Наприклад border -->
| Клітинка 1, рядок 1 
| Клітинка 2, рядок 1 
|- 
| Клітинка 1, рядок 2 
| Клітинка 2, рядок 2 
|}
\end{verbatim}

Детальніше про таблиці можна прочитати у \cite{wikitables}.
\section{Математика}
Для набору математичних формул використовується математичне середовище \LaTeX, яке вмикається всередині тегів \verb!<math></math>!.

Список всіх доступних математичних символів можна знайти у\cite{wikimath}.


\section{Категорії та інтервікі}
Деякі статті, як ми вже згадували в розділі про види сторінок попадають на особливі сторінки, які називаються категоріями. Щоб додати статтю в категорію потрібно десь в тексті статті (зазвичай в кінці) додати в неї посилання на категорію:
\begin{verbatim}
[[Категорія:Назва категорії]]
\end{verbatim}

Система категорій сама по собі є ієрархічною. Тобто, деякі категорії можуть бути підкатегоріями іншої категорії. Наприклад, категорія «Фізика» може включати підкатегорії «Класична механіка», «Квантова механіка» та ін. В свою чергу, до категорії «Класична механіка» належать статті «Закони Ньютона», «Імпульс» та інші. Але очевидно, що статтю не слід відносити до категорії і, одночасно, до підкатегорії цієї категорії. Виняток робиться лише для тих статей, які визначають саму категорію (наприклад, стаття «Україна» може бути віднесена і до категорії «Країни світу», і до категорії «Україна»)\cite{wikicats}.

Інтервікі - посилання на версії тієї ж статті іншими мовами. Варто також зауважити, що незважаючи на те, що всі проекти WikiMedia Foundation знаходяться на одних і тих же серверах, та мають однаковий домен, національні вікіпедії є цілком окремими сайтами, з окремими спільнотами, правилами, та наповненням. Навіть існують окремі національні відділи WikiMedia Foundation. Проте, якщо в різних мовних версіях вікіпедії є стаття про одне й те ж поняття, між ними встановлюють міжмовні зв'язки. Такі зв'язки називають інтервікі посиланнями.

Інтервікі посилання містять префікс мови в стандарті ISO 639\cite{wikiiwiki}. Загалом формат інтервікі можна записати таким регулярним виразом:
\begin{lstlisting}
iwiki_regex = r"\[\[(en|de|fr|zh|nl|pl|it|ja|es|pt|ru|sv|lt|no|fi|ca|uk|hu|cs|tr|ro|vo|eo|da|ko|id|sk|ar|vi|sr|he|bg|fa|sl|lmo|et|hr|new|te|nn|th|gl|el|ceb|simple|ms|eu|ht|bs|bpy|lb|ka|is|sq|la|br|hi|az|bn|mk|mr|sh|tl|cy|io|pms|lv|ta|su|oc|jv|nap|nds|scn|be|ast|ku|wa|af|be-x-old|an|ksh|szl|fy|frr|zh-yue|ur|ia|ga|yi|sw|als|hy|am|roa-rup|map-bms|bh|co|cv|dv|nds-nl|fo|fur|glk|gu|ilo|kn|pam|csb|kk|km|lij|li|ml|gv|mi|mt|nah|ne|nrm|se|nov|qu|os|pi|pag|ps|pdc|rm|bat-smg|sa|gd|sco|sc|si|tg|roa-tara|tt|to|tk|hsb|uz|vec|fiu-vro|wuu|war|vls|yo|diq|zh-min-nan|zh-classical|frp|lad|bar|bcl|kw|mn|haw|ang|ln|ie|wo|tpi|ty|crh|jbo|ay|zea|eml|ky|ig|or|mg|cbk-zam|kg|arc|rmy|gn|mo|so|kab|ks|stq|ce|udm|mzn|pap|cu|sah|tet|sd|lo|ba|pnb|iu|na|got|bo|dsb|chr|cdo|hak|om|my|sm|ee|pcd|ug|as|ti|av|bm|zu|pnt|nv|cr|pih|ss|ve|bi|rw|ch|arz|xh|kl|ik|bug|dz|ts|tn|kv|tum|xal|st|tw|bxr|ak|ab|ny|fj|lbe|ki|za|ff|lg|sn|ha|sg|ii|cho|rn|mh|chy|ng|kj|ho|mus|kr|hz|mwl|pa):([^\]]*)\]\]"
\end{lstlisting}

Інтервікі теж прийнято писати в кінці статті, одразу після категорій, незважаючи на те, що вони працюють з будь-якого місця статті. Приклад інтервікі посилань в статті "Стаття":
\begin{verbatim}
[[en:Article]]
[[eo:Artikolo]]
\end{verbatim}

В ідеалі набір статтей різними мовами про одну сутність та інтервікі посилання між ними мають утворювати повний граф (щоб за допомогою одного гіперпереходу можна було перейти на потрібну мову). Проте, якщо кількість мовних версій вже досить велика, це досить втомливо для редактора. Тоді в дію вступають інтервікі-боти. Якщо статті не містять інтервікі-конфліктів, та інтервікі-посилання утворюють зв'язний граф - бот доповнює його до повного.


\begin{description}
\item[Інтервікі-конфлікт] - ситуація, в якій по інтервікі-посиланнях можна зробити перехід між двома різними статтями однієї мови.

Проблемою є те, що одні мови можуть об'єднувати кілька понять в одне, інші навпаки. Відомим є приклад з снігом та ескімосами, та в вікіпедії трапляються і складніші випадки. Наприклад в чеській мові слово "Predikát" означає приставку для шляхетських імен (наприклад "фон"), і пов'язане з статтями що називаються "von" в інших мовах, та "Adelsprädikat" в німецькій. Але також воно означає й відомий нам предикат, що створило величезну плутанину, яку можна побачити на ілюстрації \ref{iwikiconflict}.
\end{description}

\begin{figure}
\includegraphics[width=0.4\textwidth]{predicat_iwikis.png} 
\centering \caption{Приклад інтервікіконфлікту}
\label{iwikiconflict}
\end{figure}

\section{Шаблони}
Шаблони у Вікіпедії є спеціальним класом сторінок, що їх вміст динамічно підставляється в текст інших сторінок при кожному їх перегляді.

Вікі-розмітка для виклику шаблону у статті:

\begin{verbatim}
{{Ім'я шаблону}}
\end{verbatim}

При перегляді сторінки, замість цього тегу буде вставлено текст шаблону «Шаблон:Ім'я шаблону».\cite{wikitemplates}

Параметри шаблону застосовують в тому разі, коли необхідно передбачити можливість дописати в шаблон певну інформацію, оригінальну для кожної даної статті. 

Параметри шаблону можуть бути іменованими чи нумерованими. Варіанти синтаксису:

\begin{verbatim}
{{templatename|parname1=parvalue1|parname2=parvalue2}},
\end{verbatim}

тоді у тексті шаблону слід посилатися на \verb!{{{parname}}}!;

\begin{verbatim}
{{templatename|parvalue1|parvalue2}},
\end{verbatim}

тоді у тексті шаблону слід використовувати \verb!{{{1}}}!, \verb!{{{2}}}!.

Зайві параметри (що не використовуються в тексті шаблону) ігноруються. Імена параметрів чутливі до регістру, пробілів, підкреслень та інших символів не з набору \verb![a-z\-A-Z0-9]! не допускаються.

Зверніть увагу на потрійні фігурні дужки при використанні параметрів!

Таким чином, механізм шаблонів виконує два типи підстановок:
\begin{enumerate}
\item виклик шаблону (подвійні фігурні дужки) підмінюється вмістом шаблону;
\item параметри шаблону (потрійні фігурні дужки) підмінюються значеннями параметрів шаблону.
\end{enumerate}

Якщо шаблон містить тег категорії, то у зазначену категорію відноситься не тільки шаблон, але також усі сторінки що його використовують, тому шаблони зручно використовувати для рубрикації статей.

З цим підходом пов'язана проблема кешування — якщо змінити категорію у шаблоні, статті де він використовуються будуть віднесені до нової категорії тільки після збереження будь-яких редагувань цих статей(важливим є збереження змін, саме редагування може бути порожнім).

Для розміщення у шаблоні додаткової інформації - наприклад правил використання шаблону або категорії шаблону, яка не повинна відображатись в статтях, в яку включається даний шаблон, таку інформацію слід розмістити наступним чином: \verb!<noinclude>Додаткова інформація (''наприклад'': шаблон використовується для...)</noinclude>!. В протилежному випадку - якщо нам слід закласти в шаблон інформацію, яка має відображатись в статтях, в яких цей шаблон включається, але не повинна впливати на сам шаблон (найчастіше це - категоризація статті) - слід писати \verb!<includeonly>Додаткова інформація, (''наприклад:'' [[Категорія статті]]) </includeonly>!.

\section{Магія}
Також вікірозмітка має містить деякі езотеричні елементи - магічні слова. 

Магічними словами можуть бути\cite{wikimagic}:
\begin{itemize}
\item слова, написані великими буквами, з двома нижніми рисками по боках, наприклад \verb!__NOTOC__! (не генерувати зміст сторінки)
\item парсерні функції: схожі на шаблони слова з "\verb!{{!" на початку та "\verb!}}!" в кінці, і параметрами між символами вертикальної риски («\verb!|!»), необов'язковими, за винятком частини перед першою вертикальною рискою (без риски це текст між дужками), яка містить двокрапку («:»), наприклад \verb!{{ns:3}}! і \verb!{{#ifexpr:{{{1}}}>3|велике|мале}}!
\item змінні: слова написані великими буквами, схожі на шаблони без параметрів, наприклад \verb!{{ПОТОЧНИЙ_ДЕНЬ}}!
\end{itemize}

Опишемо наприклад роботу парсерних функцій. Загальний синтаксис цих функцій такий:
\begin{verbatim}
{{#функція: аргумент 1 | аргумент 2 | аргумент 3…}} 
\end{verbatim}

Наприклад функція \verb!#expr! виконує обчислення значення виразу що їй передається. При підстановці в текст статті виразу:
\begin{verbatim}
{{#expr: (100 - 32) / 9 * 5 round 0 }}
\end{verbatim}

отримаємо значення 38. Виконано перетворення $100^\circ$ за Фаренгейтом в градуси за Цельсієм з округленням до найближчого цілого числа.

Існують багато інших парсерних функцій, наприклад таких як \verb!#if!, чи \verb!#time!, про них можна прочитати детальніше в\cite{wikiparserfunc}.

\section{Лексичний аналіз}
Лексичний аналіз - це процес перетворення послідовності символів в послідовність токенів (груп символів що відповідають певним шаблонам), та визначення їх типів. Програма, чи функція що виконує лексичний аналіз, називається лексичним аналізатором, чи сканером. Часто сканер є звичайною функцію що використовується парсером (синтаксичним аналізатором), для отримання наступного токена з потоку вхідних символів в процесі компіляції. Також часто лексичний аналіз використовують для підсвітки синтаксису певних мов. 

Лексичні аналізатори пишуться досить просто через те, що кожен вид токенів зазвичай належить якійсь регулярній мові, і якщо ви знаєте регулярні вирази, то перетворення цього регулярного виразу в скінченний автомат що його розпізнає не становить жодних проблем.

Лексичний аналізатор для MediaWiki написати зовсім не просто, бо формальної специфікації синтаксису розмітки не існує. Є проекти які намагаються побудувати специфікацію синтаксису в БНФ, РБНФ та ANTRL, але вони ще не завершені. Проблеми викликає також той факт, що її граматика по-перше контекстно-залежна, а по-друге - не завжди однозначно виводиться.\cite{markupspec}

Загалом кожен лексичний аналізатор будується по схемі: шаблон -> що зробити, якщо на вхід потрапить послідовність символів яка цьому шаблону відповідає. Таку схему колись передавали Flex, який по ній писав код скінченного автомата на C. А в Python, як виявилось має для цього клас в модулі re, який чомусь не описується в документації (думаю це рано чи пізно виправлять)\cite{sexylexing}.

Наступний набір регулярних виразів, та відповідних їм типів токенів було створено емпіричним шляхом. Він дещо універсальніший ніж аналогічний набір для flex, який можна знайти на офіційній сторінці програмного забезпечення MediaWiki\cite{flexlexer}.

\begin{lstlisting}
lexer = re.Scanner([
        (r"<!--(.|\n)*?-->",comment),# comments
        #(r"<nowiki>(.*\n)*?</nowiki>",verbatim),# nowiki
        (r"<(source|math|nowiki).*?>(.|\n)*?</(\1)>",verbatim),# source
        #(r"<math>.*?</math>",verbatim),# latex
        #(r"<math>(.*\n)*?</math>",verbatim),# latex
        (iwiki_regex,interwiki), #interwikis
        (r"\[\[(File|Image):[^|\]]+\.(jpg|png|svg|gif)\|([a-z0-9]+\|)*",markup), #images, files
        (r"\[\[[^\|\]]+(\|[^\]\|]+){2,}\]\]",markup),#files in other languages
        (r"\[\[[^\|\]]+(\|[^\]\|]+)?\]\]",link), # internal links
        (r"\[[^\]]+\]",markup), # external links
        (r"(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?",markup), #external link too
        (r"\n(=+)([^\n]*)(\1)\n",header),
        (r"\|\}\}",markup),
        (r"\{\|",markup),
        (r"\|\}",markup),
        (r"\{\{",markup),
        (r"\}\}",markup),
        (r"\{",markup), # !!!
        (r"\}",markup), # !!!
        (r"\]\]",markup),
        ("<\"",text),
        (r"<[a-zA-Z/][^>]*>",html_tag),
        (r"'''",markup), 
        (r"''",markup), 
        (r"\n[*#]+:*",markup),
        (r"\n:+",markup),
        (r"\n\|-",markup),
        (r"\|",markup),
        (r"\n!",markup),
        (r"==+",markup),
        (r"=",markup),
        (r":",markup),
        (r"\s",text),
        (r"\[\]",text),#i quite surprised but it really is text
        (r"((?!''+)[^\|\{\}\[\]:=<\n])*",text),
        (r"<\s",text),
        (r"[^<]*",text)
        ])
\end{lstlisting}

\section{Наявні синтаксичні аналізатори}
mwlib - бібліотека для мови Python розроблена фірмою PediaPress для експорту вікі-розмітки в \LaTeX, і наступної ковертації в PDF для публікації на папері.\cite{mwlibpediapress}

mwlib має парсер вікі-розмітки, який повертає синтаксичне дерево. На жаль, ніякої документації про те як здійснювати редагування цього дерева, чи хоча б навігацію по ньому не виявлено.

Більше вартих уваги синтаксичних аналізаторів мною не виявлено.

\section{Транслятор у wordpress}
Якщо нам потрібно отримати чистий HTML (без стилів самої вікіпедії) ми можемо використати сам рушій MediaWiki, просто давши запит:

\begin{lstlisting}
text=get(domain+'/w/index.php?title='+name+'&action=raw')
\end{lstlisting}

Отриманий код можна буде відредагувати за допомогою BeautifulSoup, та замінити наприклад блоки з підсвіткою синтаксису Geshi (статичний HTML згенерований з PHP) на SyntaxHighlighter (працює за допомогою JavaScript, в сторінці чистий текст програми). Також замінити всі посилання на зображення згенеровані за допомогою \LaTeX на власні теги для парсера \LaTeX.

\chapter{Сутнісний словник}
\begin{quote}
Вікіпедія – не словник. \em Правило вікіпедії.
\end{quote}
\begin{quote}
Ігноруйте усі правила. \em Ще одне правило.
\end{quote}

Проблема звичайних двомовних словників в тому, що вони намагаються встановити зв’язки між словами в різних мовах. А це досить важко зробити, і встановлюється зв’язок багато до багато. Перекладачу доводиться вибирати одне з можливих слів, як варіант перекладу. 

\begin{figure}
\includegraphics[width=0.8\textwidth]{many-to-many.png} 
\centering \caption{Схема двомовного словника}
\end{figure}

Статті вікіпедії містять інформацію не про слова. Вони містять інформацію про певні сутності, якщо це так можна назвати. Назва сутності міститься в заголовку статті. Окрім цього є альтернативні назви, з яких створюють перенаправлення. Маємо множину назв для однієї сутності, серед яких можна виділити канонічну – назву статті, на яку й посилаються всі інші.

Окрім цього, стаття містить посилання на всі статті іншими мовами, а ті в свою чергу так само. Загалом, це можна представити такою схемою:
\begin{figure}
\includegraphics[width=0.8\textwidth]{edict.png} 
\centering \caption{Схема інтервікісловника}
\end{figure}

Якщо ми здійснюємо переклад, то ми шукаємо канонічну назву за даною, потім дивимось її зв’язок з канонічною назвою в іншій мові, і переклад загалом завершений. Вибирати з якихось варіантів перекладу не потрібно, бо зв’язок між сутностями 1:1.

\section{XML дампи вікіпедії}
Інтервікі я брав парсячи XML-дамп yкраїнської вікіпедії\cite{wikidump}. Для великих файлів єдиним варіантом є парсер SAX. Як я його написав – вже не пам’ятаю. Суть в тому, що код заплутаний, і одноразовий, знаходиться в файлі \verb!makedicts.py!\cite{code}.

\section{Wikipedia extraction}
Список перенаправлень англійської вікіпедії я взяв з проекту Freebase Wikipedia Extraction\cite{WEX}. На даний момент це сімдесятиметровий архів, що містить всередині TSV-файл. В кожному його рядку міститься якийсь ідентифікатор, назва перенаправлення, і назва статті на яку перенаправляють. Були проблеми з юнікодом, але в документації до модуля tsv було пояснення як їх уникнути. Там якийсь заплутаний код з кодеками.

Враховуючи те, що перенаправлень англійська вікіпедія має близько 5 мільйонів, я вирішив додавати в словник лише ті, які посилаються на статті що мають український відповідник, що зменшило розмір словника в 10 разів. 

\section{Персистентність даних}
Персистентність – це таке розумне слово, яке означає що стан об’єкта зберігається в зовнішній пам’яті. Тобто якщо вимкнуть світло чи просто вб’ють процес, і оперативна пам’ять погасне, разом з об’єктом, при наступному запуску нашого процесу об’єкт завантажиться в такому ж стані, в якому він був останнього разу. Це надзвичайно зручно, правда?

А найзручнішим об’єктом часто є асоціативний масив, в python – dictionary, який реалізує функціональне бінарне відношення.

Тим більше він найкраще підходить власне для реалізації словника. До цього я думав писати якийсь свій CRUD інтерфейс, потім додавати до нього підтримку імпорту tsv. А ще раніше взагалі серіалізував словники. Але це працювало лише поки пар було мало. Коли я скачав дамп вікіпедії – оперативна пам'ять вичерпала свої ліміти.  

Код реалізації персистентності для dictionary знаходиться у файлі \verb!filedict.py!\cite{code}, і написаний Ерезом Шіраном\cite{erezsh}.

